package com.liz.lizrpccore.beans.proxys.redis;

import com.alibaba.fastjson.JSON;
import com.liz.lizrpccore.utils.SpringContextUtils;
import com.liz.lizrpccore.beans.proxys.base.BaseProxy;
import com.liz.lizrpccore.beans.proxys.base.LizAbstractProxy;
import com.liz.lizrpccore.configs.RpcRedisConst;
import com.liz.lizrpccore.entity.LizRpcArg;
import com.liz.lizrpccore.entity.RemoteInvokeEntity;
import com.liz.lizrpccore.entity.UniqueClientId;
import com.liz.lizrpccore.templates.MyRedisTemplate;

import java.lang.reflect.Method;
import java.util.List;
import java.util.UUID;

/**
 * @author liangGongWei
 * @description
 * @create 2021-09-22 12:04
 **/

public class LizRedisProxy extends BaseProxy implements LizAbstractProxy {
    private MyRedisTemplate myRedisTemplate;
    @Override
    public <T> Object getResult(Class<T> interfaceType, Method method, Object[] args) {
        if (this.myRedisTemplate == null){
            this.myRedisTemplate = SpringContextUtils.getApplicationContext().getBean(MyRedisTemplate.class);
        }
        String className = interfaceType.getName();
        String requestId = UUID.randomUUID().toString();
        List<LizRpcArg> lizRpcArgs = super.generateArgList(args);
        RemoteInvokeEntity entity = new RemoteInvokeEntity();
        entity.setClientId(UniqueClientId.CLIENT_ID);
        entity.setArgsList(lizRpcArgs);
        entity.setRequestId(requestId);
        entity.setMethodName(method.getName());
        String val = JSON.toJSONString(entity);
        String key = RpcRedisConst.getSaveRequestRedisKey(className);
        this.myRedisTemplate.rPush(key,val);
        String result = null;
        String resultKey = RpcRedisConst.getSaveResultToRemoteRedisKey(className,UniqueClientId.CLIENT_ID,requestId);
        int count = 0;
        while (count < 1000 && result == null){
            result = this.myRedisTemplate.getStr(resultKey);
            count ++;
        }
        if (result == null){
            System.out.println("get result from remote timeout, className:" + className + ", method:" + method.getName() + ", args:" + lizRpcArgs);
        }else {
            this.myRedisTemplate.delKey(resultKey);
        }
        Class<?> returnType = method.getReturnType();
        return JSON.parseObject(result, returnType);
    }
}
